// %nameParser.cpp
// LMNO parser generator template
//
// Copyright ©2010-2011 Brigham Toskin.
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// Some portions of the Software are taken from the Public Domain.
// Based on Lemon v1.
//
////////////////////////////////////////////////////////////////////////////////
//
// This file was generated by LMNO for the %name parser.
// All user-supplied content is the property of its respective authors and is
// subject to the following copyright and licensing terms:
%%
////////////////////////////////////////////////////////////////////////////////


#include "%nameParser.h"


/* Next are that tables used to determine what action to take based on the
 * current state and lookahead token.  These tables are used to implement
 * functions that take a state number and lookahead value and return an
 * action integer.  
 *
 * Suppose the action integer is N.  Then the action is determined as
 * follows
 *
 *   0 <= N < YYNSTATE					Shift N.  That is, push the lookahead
 *										token onto the stack and goto state N.
 *
 *   YYNSTATE <= N < YYNSTATE+YYNRULE	Reduce by rule N-YYNSTATE.
 *
 *   N == YYNSTATE+YYNRULE				A syntax error has occurred.
 *
 *   N == YYNSTATE+YYNRULE+1			The parser accepts its input.
 *
 *   N == YYNSTATE+YYNRULE+2			No such action.  Denotes unused
 *										slots in the yy_action[] table.
 *
 * The action table is constructed as a single large table named yy_action[].
 * Given state S and lookahead X, the action is computed as
 *
 *	  yy_action[ yy_shift_ofst[S] + X ]
 *
 * If the index value yy_shift_ofst[S]+X is out of range or if the value
 * yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
 * is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
 * and that yy_default[S] should be used instead.  
 *
 * The formula above is for computing the action when the lookahead is
 * a terminal symbol.  If the lookahead is a non-terminal (as occurs after
 * a reduce action) then the yy_reduce_ofst[] array is used in place of
 * the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of
 * YY_SHIFT_USE_DFLT.
 *
 * The following are the tables generated in this section:
 *
 *  yy_action[]		A single table containing all actions.
 *  yy_lookahead[]	 A table containing the lookahead for each entry in
 *					 yy_action.  Used to detect hash collisions.
 *  yy_shift_ofst[]	For each state, the offset into yy_action for
 *					 shifting terminals.
 *  yy_reduce_ofst[]   For each state, the offset into yy_action for
 *					 shifting non-terminals after a reduce.
 *  yy_default[]	   Default action for each state.
 */
%%
#define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0]))

/* The next table maps tokens into fallback tokens.  If a construct
 * like the following:
 * 
 *	  %fallback ID X Y Z.
 *
 * appears in the grammer, then ID becomes a fallback token for X, Y,
 * and Z.  Whenever one of the tokens X, Y, or Z is input to the parser
 * but it does not parse, the type of the token is changed to ID and
 * the parse is retried before an error is thrown.
 */
#ifdef YYFALLBACK
static const YYCODETYPE yyFallback[] = {
%%
};
#endif /* YYFALLBACK */

// Shift-Reduce Stack //////////////////////////////////////////////////////////

void yyStack::push(const yyStackEntry& item)
{
	c.push_back(item);
}

// pop head off (and return)
yyStackEntry yyStack::pop()
{
	popped_val = c.back();
	c.pop_back();
	return popped_val;
}

// lop head off (and discard)
void yyStack::lop()
{
	c.pop_back();
}

// lop head off (and discard)
void yyStack::lop(size_t count)
{
	while (count--)
	{
		c.pop_back();
	}
}

// return a reference to TOS
yyStackEntry& yyStack::top()
{
	return c.back();
}

// access arbitrary item in stack
yyStackEntry& yyStack::operator[](size_t i)
{
	return this->c[i];
}

// empty the stack
void yyStack::clear()
{
	c.clear();
}

// return stack height
size_t yyStack::size()
{
	return c.size();
}

// is stack empty?
bool yyStack::empty()
{
	return c.empty();
}

// Main Parser Class ///////////////////////////////////////////////////////////

// Debug Tracing Data //
#ifndef NDEBUG
std::ostream* %nameParser::yyTraceStream = NULL;
string %nameParser::yyTracePrompt = "";

// the names of all terminals and nonterminals, for tracing shifts
const string %nameParser::yyTokenName[] = { 
%%
};
// the names of all rules, for tracing reduce actions
const string %nameParser::yyRuleName[] = {
%%
};
#endif /* NDEBUG */

/**
 * Turn parser tracing on by giving a stream to which to write the trace
 * and a prompt to preface each trace message.  Tracing is turned off
 * by making either argument NULL 
 *
 * Inputs:
 * <ul>
 * <li> An ostream to which trace output should be written.
 *	  If NULL, then tracing is turned off.
 * <li> A prefix string written at the beginning of every
 *	  line of trace output.  If NULL, then tracing is
 *	  turned off.
 * </ul>
 *
 * Outputs:
 * None.
 */
void %nameParser::Trace(ostream *traceStream, const string& tracePrompt)
{
#ifndef NDEBUG
	yyTraceStream = traceStream;
	yyTracePrompt = tracePrompt;
	if(yyTraceStream == NULL)
		yyTracePrompt.clear();
	else if(yyTracePrompt == "")
		yyTraceStream = NULL;
#endif
}

// shortcut overload to disable tracing
void %nameParser::Trace()
{
#ifndef NDEBUG
	yyTraceStream = NULL;
	yyTracePrompt = "";
#endif
}

// This function returns the symbolic name associated with a token value.
const string %nameParser::TokenName(int tokenType)
{
#ifndef NDEBUG
	if(tokenType>0 && tokenType<(sizeof(yyTokenName)/sizeof(yyTokenName[0])))
	{
		return yyTokenName[tokenType];
	}
	else
	{
		return "Unknown";
	}
#else
	return "";
#endif
}

/*
 * The following function deletes the value associated with a
 * symbol.  The symbol can be either a terminal or nonterminal.
 * "yymajor" is the symbol code, and "yypminor" is a pointer to
 * the value.
 */
void %nameParser::destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor)
{
	switch(yymajor)
	{
			/* Here is inserted the actions which take place when a
			 * terminal or non-terminal is destroyed.  This can happen
			 * when the symbol is popped from the stack during a
			 * reduce or during error processing or when a parser is 
			 * being destroyed before it is finished parsing.
			 *
			 * Note: during a reduce, the only symbols destroyed are those
			 * which appear on the RHS of the rule, but which are not used
			 * inside the C code.
			 */
%%
		default:
			break;   /* If no destructor action specified: do nothing */
	}
}

/*
 * Find the appropriate action for a parser given the terminal
 * look-ahead token iLookAhead.
 *
 * If the look-ahead token is YYNOCODE, then check to see if the action is
 * independent of the look-ahead.  If it is, return the action, otherwise
 * return YY_NO_ACTION.
 */
int %nameParser::find_shift_action(int iLookAhead)
{
	int i;
	int stateno = stack.top().stateno;

	i = yy_shift_ofst[stateno];
	if(i==YY_SHIFT_USE_DFLT)
	{
		return yy_default[stateno];
	}
	if(iLookAhead==YYNOCODE)
	{
		return YY_NO_ACTION;
	}
	i += iLookAhead;
	if(i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead)
	{
#ifdef YYFALLBACK
		int iFallback;			/* Fallback token */
		if(iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
		   && (iFallback = yyFallback[iLookAhead])!=0)
		{
#ifndef NDEBUG
			if(yyTraceStream)
			{
				*yyTraceStream << yyTracePrompt << "FALLBACK "
					<< yyTokenName[iLookAhead] << "=> "
					<< yyTokenName[iFallback] << std::endl;
			}
#endif
			return find_shift_action(iFallback);
		}
#endif
		return yy_default[stateno];
	}
	else
	{
		return yy_action[i];
	}
}

/*
 * Find the appropriate action for a parser given the non-terminal
 * look-ahead token iLookAhead.
 *
 * If the look-ahead token is YYNOCODE, then check to see if the action is
 * independent of the look-ahead.  If it is, return the action, otherwise
 * return YY_NO_ACTION.
 */
int %nameParser::find_reduce_action(int iLookAhead)
{
	int i;
	int stateno = stack.top().stateno;
	
	i = yy_reduce_ofst[stateno];
	if(i==YY_REDUCE_USE_DFLT)
	{
		return yy_default[stateno];
	}
	if(iLookAhead==YYNOCODE)
	{
		return YY_NO_ACTION;
	}
	i += iLookAhead;
	if(i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead)
	{
		return yy_default[stateno];
	}
	else
	{
		return yy_action[i];
	}
}

/*
 * Perform a shift action.
 */
void %nameParser::shift(int yyNewState, int yyMajor, YYMINORTYPE *yypMinor)
{
	stack.push(yyStackEntry(yyNewState, yyMajor, *yypMinor));
#ifndef NDEBUG
	if(yyTraceStream && stack.size())
	{
		int i;
		*yyTraceStream << yyTracePrompt << "Shift " << yyNewState << '\n'
			<< yyTracePrompt << "Stack: ";
		for(i=0; i < stack.size(); i++)
			*yyTraceStream << yyTokenName[stack[i].major] << ":";
		*yyTraceStream << std::endl;
	}
#endif
}

/* The following table contains information about every rule that
 * is used during the reduce.
 */
static struct {
	YYCODETYPE lhs;		 /* Symbol on the left-hand side of the rule */
	unsigned char nrhs;	 /* Number of right-hand side symbols in the rule */
} yyRuleInfo[] = {
%%
};

/*
 * Perform a reduce action and the shift that must immediately
 * follow the reduce.
 */
void %nameParser::reduce(int yyruleno)
{
	int yygoto;					 /* The next state */
	int yyact;					  /* The next action */
	YYMINORTYPE yygotominor;		/* The LHS of the rule reduced */
	yyStackEntry *yymsp;			/* The top of the parser's stack */
	int yysize;					 /* Amount to pop the stack */
	%nameARG_FETCH;
	yymsp = &stack.top();
	
#ifndef NDEBUG
	if(yyTraceStream && yyruleno>=0 
	   && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]))
	{
		*yyTraceStream << yyTracePrompt << "Reduce [" << yyRuleName[yyruleno]
		<< "]." << std::endl;
	}
#endif /* NDEBUG */
	
	switch( yyruleno)
	{
			/* Beginning here are the reduction cases.  A typical example
			 * follows:
			 *   case 0:
			 *  #line <lineno> <grammarfile>
			 *	 { ... }		   // User supplied code
			 *  #line <lineno> <thisfile>
			 *	 break;
			 */
%%
	}
	yygoto = yyRuleInfo[yyruleno].lhs;
	yysize = yyRuleInfo[yyruleno].nrhs;
	//index -= yysize;
	stack.lop(yysize);
	yyact = find_reduce_action(yygoto);
	if(yyact < YYNSTATE)
	{
		shift(yyact,yygoto,&yygotominor);
	}
	else if(yyact == YYNSTATE + YYNRULE + 1)
	{
		accept();
	}
}

/*
 * The following code executes when the parse fails
 */
void %nameParser::parse_failed()
{
	%nameARG_FETCH;
#ifndef NDEBUG
	if(yyTraceStream)
	{
		*yyTraceStream << yyTracePrompt << "(Parse failed)" << std::endl;
	}
#endif
	stack.clear();
	/* Here code is inserted which will be executed whenever the
	 * parser fails */
%%
	%nameARG_STORE; /* Suppress warning about unused %extra_argument variable */
}

/*
 * The following code executes when a syntax error first occurs.
 */
void %nameParser::syntax_error(int yymajor, YYMINORTYPE yyminor)
{
	%nameARG_FETCH;
#define TOKEN (yyminor.yy0)
%%
	%nameARG_STORE; /* Suppress warning about unused %extra_argument variable */
#undef TOKEN
}

/*
 * The following is executed when the parser accepts
 */
void %nameParser::accept()
{
	%nameARG_FETCH;
#ifndef NDEBUG
	if(yyTraceStream)
	{
		*yyTraceStream << yyTracePrompt << "Accept!" << std::endl;
	}
#endif
	stack.clear();

	/* Here code is inserted which will be executed whenever the
	 * parser accepts */
%%
	%nameARG_STORE; /* Suppress warning about unused %extra_argument variable */
}

/* The main parser program.
 * The first argument is the major token number.  The second is
 * the minor token.  The third optional argument is whatever the
 * user wants (and specified in the grammar) and is available for
 * use by the action routines.
 *
 * Inputs:
 * <ul>
 * <li> A pointer to the parser (an opaque structure.)
 * <li> The major token number.
 * <li> The minor token number.
 * <li> An option argument of a grammar-specified type.
 * </ul>
 *
 * Outputs:
 * None.
 */
void %nameParser::Parse(int yymajor, %nameTOKENTYPE yyminor %nameARG_PDECL)
{
	YYMINORTYPE yyminorunion;
	int yyact;					/* The parser action. */
	bool yyendofinput;	 		/* True if we are at the end of input */
	bool yyerrorhit = false;	/* True if yymajor has invoked an error */
	
	/* (re)initialize the parser, if necessary */
	if(stack.empty())
	{
		if(yymajor == 0)
			return;
		errCount = -1;
		stack.push(yyStackEntry());
	}
	yyminorunion.yy0 = yyminor;
	yyendofinput = (yymajor==0);
	%nameARG_STORE;
	
#ifndef NDEBUG
	if(yyTraceStream)
	{
		*yyTraceStream << yyTracePrompt << "Input " << yyTokenName[yymajor]
			<< endl;
	}
#endif
	
	do
	{
		yyact = find_shift_action(yymajor);
		if(yyact<YYNSTATE)
		{
			shift(yyact,yymajor,&yyminorunion);
			errCount--;
			if(yyendofinput && stack.size())
			{
				yymajor = 0;
			}
			else
			{
				yymajor = YYNOCODE;
			}
		}
		else if(yyact < YYNSTATE + YYNRULE)
		{
			reduce(yyact-YYNSTATE);
		}
		else if(yyact == YY_ERROR_ACTION)
		{
#ifndef NDEBUG
			if(yyTraceStream)
			{
				*yyTraceStream << yyTracePrompt << "(Syntax Error)" << endl;
			}
#endif
#ifdef YYERRORSYMBOL
			/* A syntax error has occurred.
			 * The response to an error depends upon whether or not the
			 * grammar references the error symbol "error".  
			 *
			 * This is what we do if the grammar does use error:
			 *
			 *  * Call the %syntax_error function.
			 *
			 *  * Begin popping the stack until we enter a state where
			 *	it is legal to shift the error symbol, then shift
			 *	the error symbol.
			 *
			 *  * Set the error count to three.
			 *
			 *  * Begin accepting and shifting new tokens.  No new error
			 *	processing will occur until three tokens have been
			 *	shifted successfully.
			 *
			 */
			if(errCount < 1)
			{
				syntax_error(yymajor,yyminorunion);
			}
			errCount = 3;
			yyerrorhit = true;

			int tos = stack.top().major;
			if(tos == YYERRORSYMBOL || yyerrorhit) // hit error previously
			{
#ifndef NDEBUG
				if(yyTraceStream)
				{
					*yyTraceStream << yyTracePrompt << "Discard input token: "
						<< yyTokenName[yymajor] << endl;
				}
#endif
				destructor(yymajor,&yyminorunion);
				yymajor = YYNOCODE;
			}
			else // first error
			{
				yyact = find_shift_action(YYERRORSYMBOL);
				while(stack.size() && yyact >= YYNSTATE) // can't shift
				{
					cerr << "Popping " << yyTokenName[stack.pop().major]
						 << endl;
					yyact = find_shift_action(YYERRORSYMBOL);
				}

				if(stack.empty() || yymajor == 0)
				{
					destructor(yymajor, &yyminorunion);
					parse_failed();
					yymajor = YYNOCODE;
				}
				else if(tos != YYERRORSYMBOL)
				{
					YYMINORTYPE u2;
					u2.YYERRSYMDT = 0;
					shift(yyact, YYERRORSYMBOL, &u2);
				}
			}
#else  // YYERRORSYMBOL is not defined
			/* This is what we do if the grammar does not define ERROR:
			 *
			 *  * Report an error message, and throw away the input token.
			 *
			 *  * If the input token is $, then fail the parse.
			 *
			 * As before, subsequent error messages are suppressed until
			 * three input tokens have been successfully shifted.
			 */
			if(errCount < 1)
			{
				syntax_error(yymajor,yyminorunion);
			}
			errCount = 3;
			destructor(yymajor,&yyminorunion);
			if(yyendofinput)
			{
				parse_failed();
			}
			yymajor = YYNOCODE;
#endif
		}
		else
		{
			accept();
			yymajor = YYNOCODE;
		}
	} while(yymajor != YYNOCODE && stack.size());
}
